package com.example.blog.service.impl;


import com.example.blog.entity.Article;

import com.example.blog.entity.User;
import com.example.blog.exception.ResourceNotFoundException;
import com.example.blog.modules.article.dto.FavoriteDTO;
import com.example.blog.modules.article.entity.Favorite;
import com.example.blog.modules.notification.dto.NotificationDTO;
import com.example.blog.repository.ArticleRepository;
import com.example.blog.repository.FavoriteRepository;
import com.example.blog.repository.UserRepository;
import com.example.blog.service.FavoriteService;
import com.example.blog.service.NotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class FavoriteServiceImpl implements FavoriteService {
    @Autowired
    private FavoriteRepository favoriteRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private NotificationService notificationService;

    @Override
    @Transactional
    public FavoriteDTO favoriteArticle(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        if (favoriteRepository.existsByUserAndArticle(user, article)) {
            throw new RuntimeException("You have already favorited this article");
        }

        Favorite favorite = new Favorite();
        favorite.setUser(user);
        favorite.setArticle(article);
        Favorite savedFavorite = favoriteRepository.save(favorite);

        // Create notification for article author
        if (!article.getAuthor().getId().equals(user.getId())) {
            NotificationDTO notification = new NotificationDTO();
            notification.setUserId(article.getAuthor().getId());
            notification.setTitle("New Favorite");
            notification.setMessage(user.getUsername() + " favorited your article: " + article.getTitle());
            notification.setType("FAVORITE");
            notification.setEntityId(article.getId());
            notification.setEntityType("ARTICLE");
            notificationService.createNotification(notification);
        }

        return convertToDTO(savedFavorite);
    }

    @Override
    @Transactional
    public void unfavoriteArticle(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        Favorite favorite = favoriteRepository.findByUserAndArticle(user, article)
                .orElseThrow(() -> new ResourceNotFoundException("Favorite", "article_id", articleId));

        favoriteRepository.delete(favorite);
    }

    @Override
    public boolean hasFavorited(Long articleId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User", "username", username));

        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return favoriteRepository.existsByUserAndArticle(user, article);
    }

    @Override
    public Page<FavoriteDTO> getUserFavorites(Long userId, Pageable pageable) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));

        return favoriteRepository.findByUser(user, pageable)
                .map(this::convertToDTO);
    }

    @Override
    public Page<FavoriteDTO> getArticleFavorites(Long articleId, Pageable pageable) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return favoriteRepository.findByArticle(article, pageable)
                .map(this::convertToDTO);
    }

    @Override
    public long getArticleFavoritesCount(Long articleId) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ResourceNotFoundException("Article", "id", articleId));

        return favoriteRepository.countByArticle(article);
    }

    private FavoriteDTO convertToDTO(Favorite favorite) {
        FavoriteDTO dto = new FavoriteDTO();
        dto.setId(favorite.getId());
        dto.setUserId(favorite.getUser().getId());
        dto.setUsername(favorite.getUser().getUsername());
        dto.setArticleId(favorite.getArticle().getId());
        dto.setArticleTitle(favorite.getArticle().getTitle());
        dto.setCreatedAt(favorite.getCreatedAt());
        return dto;
    }
} 